package com.itheima.manage.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.dubbo.config.annotation.Reference;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.commons.pojo.*;
import com.itheima.commons.vo.*;
import com.itheima.interfaces.*;
import org.bson.types.ObjectId;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class ManageService {

    @Reference
    private FreezeApi freezeApi;
    @Reference
    private UserInfoApi userInfoApi;
    @Reference
    private UserApi userApi;
    @Reference
    private UsersApi usersApi;
    @Reference
    private UserLoginApi userLoginApi;
    @Reference
    private LastLoginApi lastLoginAoi;
    @Reference
    private PublishApi publishApi;
    @Reference
    private AlbumApi albumApi;
    @Reference
    private AuditStateApi auditStateApi;
    @Reference
    private VideosApi videosApi;
    @Reference
    private CommentApi commentApi;
    static String[] city = {"上海", "杭州", "波士顿", "加拿大", "台湾"};
    static String[] device = {"小米手机", "苹果手机", "苹果电脑", "华为手机", "苹果手表"};
    static String[] signature = {"不顾别人感受是自私，太顾别人感受是自虐。", "年龄永远不是衡量一个人的刻度，只有责任的叠加才会让人逐渐成长。", "昨天再好，也走不回去；明天再难，也要抬脚继续。", "时间，带不走真正的朋友；岁月，留不住虚幻的拥有。", "人生充满了起起落落，关键在于，在顶端时要好好享受，在低谷时不失勇气。\n" +
            "\n"};

    /**
     * 用户冻结操作
     *
     * @param freeze 被操作实体
     * @return
     */
    public Boolean addFreeze(Freeze freeze) {
        //冻结操作
        freeze.setState(1);
        Boolean message = freezeApi.addFreeze(freeze);
        //记录操作日志

        return message;
    }

    /**
     * 用户解冻操作
     *
     * @param userId            被解冻Id
     * @param reasonsForThawing 被解冻原因
     * @return
     */
    public Boolean deleteFreezeByUserId(Integer userId, String reasonsForThawing) {
        //解除冻结
        Boolean message = freezeApi.deleteFreezeByUserId(userId);
        //记录操作日志 记录解冻理由

        return message;
    }

    /**
     * 查询用户的基本资料
     *
     * @param userId 被查询Id
     * @return
     */
    public BasicUserInfoVo queryBasicUserInfoByUserId(String userId) {
        Long userIdL = Convert.toLong(userId);
        //根据userId查UserInfo
        UserInfo userInfo = userInfoApi.findUserInfoByUserId(userIdL);
        //查询用户的手机号
        User user = userApi.selectPhoneById(userIdL);
        //根据userId查用户冻结状态

        //拼装BasicUserInfoVo对象
        BasicUserInfoVo basicUserInfoVo = new BasicUserInfoVo();
        basicUserInfoVo.setId(Convert.toLong(userId));//用户Id
        basicUserInfoVo.setMobile(user.getMobile());//手机号，即用户账号

        basicUserInfoVo.setNickname(userInfo.getNickName());//昵称
        basicUserInfoVo.setSex(userInfo.getSex() == 1 ? "男" : "女");//性别
        basicUserInfoVo.setLogo(userInfo.getLogo());//用户头像
        basicUserInfoVo.setTags(userInfo.getTags());//用户标签
        basicUserInfoVo.setIncome(Convert.toInt(userInfo.getIncome()));//收入
        basicUserInfoVo.setOccupation(userInfo.getIndustry());//职业
        basicUserInfoVo.setAge(userInfo.getAge());//年龄
        basicUserInfoVo.setCreated(DateUtil.parse(userInfo.getCreated()).getTime());//注册时间

        //查询喜欢
        Long countLove = usersApi.selectLove(userIdL);
        basicUserInfoVo.setCountBeLiked(Convert.toInt(countLove));//被喜欢人数

        //查询粉丝
        Long countFans = usersApi.selectFans(userIdL);
        basicUserInfoVo.setCountLiked(Convert.toInt(countFans));//喜欢人数
        //查询互相喜欢
        List<Long> idList = usersApi.selectLoveId(userIdL);//查询自己喜欢人的id
        Long eachLoveCount = usersApi.selectEachLove(idList, userIdL);
        basicUserInfoVo.setCountMatching(Convert.toInt(eachLoveCount));//配对人数

        Freeze freeze = freezeApi.quweyFreezeByUserId(userIdL);
        basicUserInfoVo.setUserStatus(ObjectUtil.isNull(freeze) ? "1" : "2");//用户状态，1为正常，2为冻结

        Long lastLoginTime = lastLoginAoi.findLastLoginByUserId(userInfo.getUserId()).getLastLoginTime().getTime();
        basicUserInfoVo.setLastActiveTime(lastLoginTime);//最近活跃时间
        basicUserInfoVo.setPersonalSignature(signature[RandomUtil.randomInt(0, 5)]);//个性签名
        basicUserInfoVo.setCity(userInfo.getCity());//注册地区
        basicUserInfoVo.setLastLoginLocation(userInfo.getCity());//最近登录地

        return basicUserInfoVo;
    }

    /**
     * 用户数据翻页
     *
     * @param
     * @return
     */
    public PageResult queryUsersByQueryUserInfoConditions(Integer page, Integer pagesize, Long userId, String nickname, String city) {
        //判断是否有模糊查询的条件
        if (ObjectUtil.isAllEmpty(userId, nickname, city)) {
            //没有模糊查询条件
            Page<LastLogin> userInfoPage = lastLoginAoi.queryLastLogins(page, pagesize);
            Long counts = userInfoPage.getTotal();
            List<LastLogin> lastLoginList = userInfoPage.getRecords();
            //根据据UIds查询UserInfo
            List<Long> userIds = CollUtil.getFieldValues(lastLoginList, "userId", Long.class);
            //调用getUserManageVos方法 获取List<UserManageVo>
            List<UserManageVo> userManageVos = getUserManageVos(lastLoginList, userInfoApi.findPublishInfo(userIds));

            return new PageResult(page, pagesize, counts, userManageVos);
        }

        //若查询条件都不为空
        Page<UserInfo> userInfoPage = userInfoApi.queryUserInfosByPage(page, pagesize, userId, nickname, city);
        Long counts = userInfoPage.getTotal();
        List<UserInfo> userInfoList = userInfoPage.getRecords();
        Map<Long, UserInfo> userInfoMap = CollUtil.fieldValueMap(userInfoList, "userId");
        //根据上面的用户Id查询LastLogin
        List<Long> userIds = CollUtil.getFieldValues(userInfoList, "userId", Long.class);
        List<UserManageVo> userManageVos = getUserManageVos(lastLoginAoi.queryLastLoginList(userIds), userInfoMap);

        return new PageResult(page, pagesize, counts, userManageVos);

    }


    /**
     * 消息翻页
     *
     * @param page      页尺寸
     * @param pageSize  页数
     * @param sortProp  排序字段 必须
     * @param sortOrder ascending 升序 descending 降序 必须
     * @param id        消息id
     * @param sd        开始时间
     * @param ed        结束时间
     * @param uid       用户ID 必须
     * @param state     审核状态 必须
     * @return
     */
    public MessagesPageResultPuls queryMessages(Integer page, Integer pageSize, String sortProp, String sortOrder, Long id, Long sd, Long ed, Long uid, String state) {
        //根据传输的数据是否为空判断几种情况 用户ID、消息id、开始时间结束时间 进行区分
        //分为 用户动态记录查询、动态详情、动态管理二个展示视图 这里我们需要专门写一个封装方法将共性抽取出来

        // 当用户Id不为空 state为空时 执行用户动态记录查询
        if (ObjectUtil.isNotNull(uid) && ObjectUtil.isEmpty(state)) {
            //根据用户Id查询 UsrInfo
            UserInfo userInfo = userInfoApi.findUserInfoByUserId(uid);
            //根据用户Id分面保存着用户发布过得所有动态 这里用到分页查询下 根据排序字段排序 指定升降序 暂时无法实现
            List<Album> albums = albumApi.selectByUserIdAndDesc(page, pageSize, uid);
            List<ObjectId> publishIds = CollUtil.getFieldValues(albums, "publishId", ObjectId.class);
            //调用编写的String集合转译ObjectId集合方法
            List<Publish> publishes = publishApi.queryPublishes(publishIds);
            //调用getMessagesVos方法拼接 List<MessagesVo>
            List<MessagesVo> messagesVos = getMessagesVos(publishes, ListUtil.toList(userInfo));
            //totals 拼装 MessagesStateVo
            Long total = albumApi.findCountByUserId(uid);
            return new MessagesPageResultPuls(page, pageSize, total, messagesVos, null);
        }

        //这是一个公用接口 我们要判断两种情况 因为用户id的存在他说查询的单个用户的 UserInfo拿取信息
        //动态管理每次传参state 审核状态 不会为空
        Page<AuditState> auditStatePage = auditStateApi.queryAuditStatesByStateAndPage(page, pageSize, state, id, sd, ed);
        List<AuditState> auditStates = auditStatePage.getRecords();
        List<String> publishIds = CollUtil.getFieldValues(auditStates, "publishId", String.class);
        List<Publish> publishes = publishApi.queryPublishes(getObjectId(publishIds));
        List<Long> userIds = CollUtil.getFieldValues(publishes, "userId", Long.class);
        List<UserInfo> userInfos = userInfoApi.queryPublishInfos(userIds);
        //调用getMessagesVos方法拼接 List<MessagesVo>
        List<MessagesVo> messagesVos = getMessagesVos(publishes, userInfos);
        //totals 拼装 MessagesStateVo
        Long total = auditStatePage.getTotal();
        return new MessagesPageResultPuls(page, pageSize, total, messagesVos, getMessagesStateVos(id, sd, ed));
    }

    //userManageVo封装方法
    public List<UserManageVo> getUserManageVos(List<LastLogin> lastLoginList, Map<Long, UserInfo> userInfoMap) {
        //返回值Vo集合
        List<UserManageVo> userManageVos = new ArrayList<>();
        //拼装vo UserManageVo
        for (LastLogin lastLogin : lastLoginList) {

            UserManageVo userManageVo = new UserManageVo();
            UserInfo userInfo = userInfoMap.get(lastLogin.getUserId());

            userManageVo.setId(Convert.toInt(userInfo.getUserId()));//用户Id
            userManageVo.setLogo(userInfo.getLogo());//头像
            userManageVo.setNickname(userInfo.getNickName());//昵称
            userManageVo.setSex(userInfo.getSex() == 1 ? "男" : "女");//性别
            userManageVo.setAge(userInfo.getAge());//年龄
            userManageVo.setOccupation(userInfo.getIndustry());//职业
            //注册城市名称，城市信息叶子节点名称即可，无需adcode
            userManageVo.setCity(StrUtil.splitToArray(userInfo.getCity(), "-")[0]);
            //手机号，即用户账号
            userManageVo.setMobile(userApi.selectPhoneById(userInfo.getUserId()).getMobile());
            //用户状态
            userManageVo.setUserStatus(ObjectUtil.isNull(freezeApi.quweyFreezeByUserId(userInfo.getUserId())) ? "1" : "2");
            //最近活跃时间
            userManageVo.setLastActiveTime(lastLogin.getLastLoginTime().getTime());
            //头像状态 ,1通过，2拒绝
            userManageVo.setLogoStatus("");

            //保存封装对象
            userManageVos.add(userManageVo);
        }

        return userManageVos;
    }

    //MessagesVo集合封装方法
    public List<MessagesVo> getMessagesVos(List<Publish> publishes, List<UserInfo> userInfos) {
        if (CollUtil.isEmpty(publishes)) {
            List<MessagesVo> messagesVos = new ArrayList<>();
            return messagesVos;
        }

        Map<Long, UserInfo> userInfoMap = CollUtil.fieldValueMap(userInfos, "userId");
        //封装Vo
        List<MessagesVo> messagesVos = new ArrayList<>();
        for (Publish publish : publishes) {
            MessagesVo messagesVo = new MessagesVo();

            messagesVo.setNickname(userInfoMap.get(publish.getUserId()).getNickName());//作者昵称
            messagesVo.setId(publish.getId().toHexString());//编号
            messagesVo.setUserId(publish.getUserId());//作者ID
            messagesVo.setUserLogo(userInfoMap.get(publish.getUserId()).getLogo());//作者头像
            messagesVo.setCreateDate(publish.getCreated());//发布日期
            messagesVo.setText(publish.getText());//正文
            //审核状态，1为待审核，2为自动审核通过，3为待人工审核，4为人工审核拒绝，5为人工审核通过，6为自动审核拒绝
            AuditState auditState = auditStateApi.queryAuditState(publish.getId().toHexString());//没做假数据查不到
            messagesVo.setState(ObjectUtil.isNull(auditState) ? "" : auditState.getState());//放在返回null报错
            //置顶状态，1为未置顶，2为置顶
            messagesVo.setTopState(ObjectUtil.isNull(auditState) ? 1 : auditState.getTopState());
            //图片列表
            messagesVo.setMedias(Convert.toStrArray(publish.getMedias()));
            //点赞数
            messagesVo.setLikeCount(publishApi.findCount(publish.getId(), 1));
            //评论数
            messagesVo.setCommentCount(publishApi.findCount(publish.getId(), 2));
            //举报数
            messagesVo.setReportCount(Convert.toLong(RandomUtil.randomInt(30)));
            //转发数
            messagesVo.setForwardingCount(Convert.toLong(RandomUtil.randomInt(30)));

            messagesVos.add(messagesVo);
        }
        return messagesVos;
    }

    //MessagesStateVo集合的封装方法
    public List<MessagesStateVo> getMessagesStateVos(Long id, Long sd, Long ed) {

        List<MessagesStateVo> messagesStateVos = new ArrayList<>();

        Long num = auditStateApi.findNumByState(null, id, sd, ed);
        messagesStateVos.add(MessagesStateVo.builder().title("全部").code("all").value(num).build());
        //根据状态查数量
        Long num3 = auditStateApi.findNumByState("3", id, sd, ed);
        messagesStateVos.add(MessagesStateVo.builder().title("待审核").code("3").value(num3).build());
        //根据状态查数量
        Long num4 = auditStateApi.findNumByState("4", id, sd, ed);
        messagesStateVos.add(MessagesStateVo.builder().title("已通过").code("4").value(num4).build());
        //根据状态查数量
        Long num5 = auditStateApi.findNumByState("5", id, sd, ed);
        messagesStateVos.add(MessagesStateVo.builder().title("已驳回").code("5").value(num5).build());

        return messagesStateVos;
    }

    //String集合转译ObjectId集合方法
    public List<ObjectId> getObjectId(List<String> stringList) {
        List<ObjectId> objectIdList = new ArrayList<>();
        for (String s : stringList) {
            ObjectId objectId = new ObjectId(s);
            objectIdList.add(objectId);
        }
        return objectIdList;
    }

    /**
     * 消息详情
     *
     * @param id 动态Id
     * @return
     */
    public MessagesVo queryMessageById(String id) {
        Publish publish = publishApi.queryById(new ObjectId(id));
        UserInfo userInfo = userInfoApi.findUserInfoByUserId(publish.getUserId());
        //调用getMessagesVos 封装方法
        List<MessagesVo> messagesVos = getMessagesVos(CollUtil.toList(publish), CollUtil.toList(userInfo));
        return messagesVos.get(0);
    }


    /**
     * 消息置顶设置
     *
     * @param id
     * @return
     */
    public Boolean setAuditStateTop(String id, Integer topState) {
        return auditStateApi.setAuditStateTopState(id, topState);
    }

    /**
     * 消息状态设置多选操作
     *
     * @param publishIds 动态Id数组
     * @return
     */
    public Boolean revocation(String[] publishIds, String state) {

        return auditStateApi.updateAuditState(publishIds, state);
    }

    public PageResult userVideoLogs(Integer page, Integer pageSize, String sortProp, String sortOrder, Long uid) {
        List<Video> list = videosApi.pageVideoLogs(page, pageSize, sortProp, StrUtil.sub(sortOrder, 0, -6), uid);
        List<VideoLogVo> vo = list.stream().map(video -> {
            VideoLogVo videoLogVo = new VideoLogVo();
            videoLogVo.setId(Convert.toLong(video.getId()));
            videoLogVo.setUserId(video.getUserId());
            UserInfo userInfo = userInfoApi.findUserInfoByUserId(video.getUserId());
            videoLogVo.setNickname(userInfo.getNickName());
            videoLogVo.setVideoUrl(video.getVideoUrl());
            videoLogVo.setPicUrl(video.getPicUrl());
            videoLogVo.setReportCount(RandomUtil.randomLong(100L));
            videoLogVo.setForwardingCount(RandomUtil.randomLong(10L));
            videoLogVo.setLikeCount(commentApi.selectLikeSize(video.getId().toHexString()));
            videoLogVo.setCommentCount(commentApi.selectCommentSize(video.getId().toHexString()));
            videoLogVo.setCreateDate(video.getCreated());

            return videoLogVo;

        }).collect(Collectors.toList());

        return new PageResult(page, pageSize, Convert.toLong(list.size()), vo);
    }

    public PageResult userLoginLogs(Integer page, Integer pageSize, String sortProp, String sortOrder, Long uid) {
        Page<UserLogin> pageLogin = userLoginApi.pageLoginLogs(page, pageSize, StrUtil.sub(sortOrder, 0, -6), uid);
        List<UserLogin> records = pageLogin.getRecords();
        List<LoginLogVo> vo = new ArrayList<>();
        for (UserLogin record : records) {
            LoginLogVo loginLogVo = new LoginLogVo();
            loginLogVo.setId(record.getId());
            loginLogVo.setLogTime(record.getLoginTime().getTime());
            loginLogVo.setPlace(city[RandomUtil.randomInt(5)]);
            loginLogVo.setEquipment(device[RandomUtil.randomInt(5)]);
            vo.add(loginLogVo);
        }
        return new PageResult(page, pageSize, pageLogin.getTotal(), vo);
    }

    public PageResult userCommentsLogs(Integer page, Integer pageSize, String sortProp, String sortOrder, String messageID) {
        //查询评论
        List<Comment> commentList = commentApi.pageCommentsLogs(page, pageSize, sortProp, sortOrder, new ObjectId(messageID));
        List<CommentsVo> commentsVoList = new ArrayList<>();
        for (Comment comment : commentList) {
            CommentsVo commentsVo = new CommentsVo();
            commentsVo.setId(comment.getId().toHexString());
            UserInfo userInfo = userInfoApi.findUserInfoByUserId(comment.getUserId());
            commentsVo.setNickname(userInfo.getNickName());
            commentsVo.setUserId(Convert.toInt(comment.getUserId()));
            commentsVo.setContent(comment.getContent());
            commentsVo.setCreateDate(Convert.toInt(comment.getCreated()));
            commentsVoList.add(commentsVo);
        }
        return new PageResult(page, pageSize, Convert.toLong(commentList.size()), commentsVoList);
    }
}
